﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using org.se.fs.presenter.IView.Template;
using org.se.fs.presenter.Library;
using org.se.fs.presenter.Task.Template;

namespace org.se.fs.presenter.View.Template
{
    public abstract class ViewLists
    {
        public event FormEvent.FormEventHandler OnToggle;
        public event FormEvent.FormEventHandler OnDelete;
        public event FormEvent.FormEventHandler OnError;
        protected IFormLists View;
        protected Crud Task;
        protected DataTable Lists;
        protected UInt16 CurrPage;
        protected UInt16 MaxRecords;
        protected IList<SearchOption> SearchOption;

        public virtual void Initialize()
        {
            Lists = new DataTable();
            Task.OnFetchLists += TaskOnFetchLists;
            Task.OnDelete += TaskOnDelete;
            Task.OnToggle += TaskOnToggle;
            Task.OnError += TaskOnError;
            Task.OnGetCount += TaskOnGetCount;
            Task.OnGetActive += TaskOnGetActive;
            Task.OnGetById += TaskOnGetById;
            Task.OnGetId += TaskOnGetId;
            InitializeSearchOption();
            Search();
        }

        public void TriggerToggle(FormEvent e)
        {
            if (OnToggle != null)
                OnToggle(this, e);
        }

        public void TriggerDelete(FormEvent e)
        {
            if (OnDelete != null)
                OnDelete(this, e);
        }

        public void TriggerError(FormEvent e)
        {
            if (OnError != null)
                OnError(this, e);
        }

        protected virtual void TaskOnFetchLists(object source, FormEvent e)
        {
            View.EnableButtonSearch(true);
            View.EnableResults(true);
            Lists = (DataTable)e.Value;
            DisplayData();
        }

        protected virtual void TaskOnDelete(object source, FormEvent e)
        {
            TriggerDelete(new FormEvent(true) { Exception = e.Exception });

            if (!e.IsSuccess)
                return;

            var data = (DataTable)e.Value;
            foreach (var dr in Lists.Select().Where(dr => dr["id"].ToString().Equals(data.Rows[0]["id"].ToString())))
            {
                Lists.Rows.Remove(dr);
                break;
            }
            DisplayData();   
        }

        protected virtual void TaskOnToggle(object source, FormEvent e) { }

        protected virtual void TaskOnError(object source, FormEvent e) { }

        protected virtual void TaskOnGetCount(object source, FormEvent e)
        {
            MaxRecords = (UInt16)e.Value;
            FetchRecords();
        }

        protected virtual void TaskOnGetActive(object source, FormEvent e) { }

        protected virtual void TaskOnGetById(object source, FormEvent e) { }

        protected virtual void TaskOnGetId(object source, FormEvent e) { }

        protected virtual void InitializeSearchOption() { }

        public virtual void Add(DataRow data)
        {
            if (data.ItemArray.Length.Equals(0)) 
                return;
            Lists.Rows.Add(data);
            DisplayData();
        }

        public virtual void Modify(DataRow data)
        {
            if (data == null || data.ItemArray.Length.Equals(0))
                return;

            foreach (var dr in Lists.Select().Where(dr => dr["id"].ToString().Equals(data["id"].ToString())))
            {
                dr.ItemArray = data.ItemArray;
                break;
            }
            DisplayData();
        }

        public virtual void Remove(DataRow data)
        {
            if (data.ItemArray.Length.Equals(0)) 
                return;
            Task.Delete(data);  
        }

        public virtual void Toggle(uint index, bool active) { }

        public virtual void Search()
        {
            View.EnableButtonSearch(false);
            Task.GetCount();
        }

        protected virtual string GetFilterString()
        {
            if (string.IsNullOrEmpty(View.SearchItem) || View.IndexType.Equals(-1))
                return string.Empty;

            return
                string.Format(
                    SearchOption[View.IndexType].DataType.Equals(typeof(string)) ? "{0} LIKE {1}%" : "{0} {1}",
                    SearchOption[View.IndexType].Filter, View.SearchItem);
        }

        public DataRow GetData(int index)
        {
            var a = Lists.NewRow();
            a.ItemArray = Lists.Rows[index].ItemArray;
            return a;
        }

        public virtual void DisplayData() {}

        protected virtual void SetStatusPage()
        {
            var a = CurrPage - Config.MaxPageSize < 0;
            View.EnableButtonRecordFirst(!a);
            View.EnableButtonRecordPrevious(!a);

            var b = CurrPage + Config.MaxPageSize > MaxRecords;
            View.EnableButtonRecordNext(!b);
            View.EnableButtonRecordLast(!b);

            View.StatusPage = string.Format("( {0} / {1} of {2} Records)", CurrPage, CurrPage + Config.MaxPageSize,
                                             MaxRecords);
        }

        public virtual DataRow EmptyRecord()
        {
            return Lists.NewRow();
        }

        protected virtual void FetchRecords()
        {
            View.EnableResults(false);
            Task.FetchLists(new PagingLists(CurrPage, GetFilterString()));
        }

        public virtual void MoveToFirstRecord()
        {
            CurrPage = 0;
            FetchRecords();
        }

        public virtual void MoveToPreviousRecord()
        {
            if (CurrPage - Config.MaxPageSize <= 0)
            {
                MoveToFirstRecord();
                return;
            }

            CurrPage -= Config.MaxPageSize;
            FetchRecords();
        }

        public virtual void MoveToNextRecord()
        {
            if (CurrPage + Config.MaxPageSize >= MaxRecords)
            {
                MoveToLastRecord();
                return;
            }

            CurrPage += Config.MaxPageSize;
            FetchRecords();
        }

        public virtual void MoveToLastRecord()
        {
            CurrPage = (UInt16)Math.Floor((MaxRecords / (decimal)Config.MaxPageSize) * Config.MaxPageSize);
            CurrPage -= (UInt16)(CurrPage % Config.MaxPageSize);
            FetchRecords();
        }
    }
}